home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -seriously_amiga- / shareware / programming / c / vbcc / pasm / main.c < prev    next >
C/C++ Source or Header  |  1998-01-05  |  8KB  |  268 lines

  1. /* $VER: pasm main.c V0.6 (30.10.97)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-97 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.6 (30.10.97) phx
  16.  *      Options to disable warnings for optional, 64-bit and super-
  17.  *      visor instructions: -mo, -m64, -ms.
  18.  * v0.5 (12.10.97) phx
  19.  *      Option -D defines symbols. If an '=' is missing, a default
  20.  *      value of '1' will be assigned. Assignment of symbols, which
  21.  *      are defined later in the source, is also allowed.
  22.  * v0.4 (05.07.97) phx
  23.  *      Program returns EXIT_FAILURE if an error occurs.
  24.  *      -V prints only version and build string and no instructions.
  25.  *      Base address for absolute code may be set with -B option.
  26.  *      EHF support.
  27.  *      New option -I to specify some include paths.
  28.  *      Option -x automatically declares unknown symbols as
  29.  *      externally defined.
  30.  * v0.2 (25.03.97) phx
  31.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  32.  *      or ELF output format may be selected. ELF is default for all
  33.  *      currently supported platforms. PPCasm supports nine different
  34.  *      relocation types (there are much more...).
  35.  *      Compiles and works also under NetBSD/amiga (68k).
  36.  *      Changed function declaration to 'new style' in all sources
  37.  *      (to avoid problems with '...' for example).
  38.  *      Supports multiple output formats. Currently Absolute and ELF.
  39.  * v0.1 (11.03.97) phx
  40.  *      First test version with all PowerPC instructions and most
  41.  *      important directives. Only raw, absolute output.
  42.  * v0.0 (14.02.97) phx
  43.  *      File created. Project started.
  44.  */
  45.  
  46.  
  47. #define MAIN_C
  48. #include "ppcasm.h"
  49.  
  50.  
  51. struct GlobalVars gvars;
  52.  
  53.  
  54. void cleanup(struct GlobalVars *);
  55.  
  56. static char *default_destname(struct GlobalVars *);
  57. static char *get_option_arg(int,char *[],int *);
  58. static void write_object(struct GlobalVars *);
  59.  
  60.  
  61.  
  62. main(int argc,char *argv[])
  63. {
  64.   struct GlobalVars *gv = &gvars;
  65.   int i,j;
  66.   char *buf;
  67.   char *stdassgn = "1";  /* default assignment for user definitions */
  68.   struct UserDefine *udn;
  69.  
  70.   /* initialize and set default values */
  71.   memset(gv,0,sizeof(struct GlobalVars));
  72.   gv->maxerrors = DEF_MAXERRORS;
  73.   gv->output = OFMT_DEFAULT;  /* default output format */
  74.   initlist(&gv->sourcelist);
  75.   initlist(&gv->sectionlist);
  76.   initlist(&gv->userdeflist);
  77.  
  78.   if (argc<2 || (argc==2 && *argv[1]=='?')) {
  79.     show_usage();
  80.     exit(EXIT_SUCCESS);
  81.   }
  82.   for (i=1; i<argc; i++) {
  83.     if (*argv[i] == '-') {
  84.       /* option detected */
  85.       switch (argv[i][1]) {
  86.  
  87.         case 'V':  /* show version */
  88.           show_version();
  89.           exit(EXIT_SUCCESS);
  90.  
  91.         case 'o':  /* set output file */
  92.           if (!(gv->dest_name = get_option_arg(argc,argv,&i)))
  93.             error(3);  /* missing output file name */
  94.           break;
  95.  
  96.         case 'w':  /* suppress warnings */
  97.           gv->dontwarn = TRUE;
  98.           break;
  99.  
  100.         case 'x':  /* auto extern */
  101.           gv->autoextern = TRUE;
  102.           break;
  103.  
  104.         case 'R':  /* don't predefine register symbols, etc. */
  105.           gv->noregsymbols = TRUE;
  106.           break;
  107.  
  108.         case 'X':  /* no extended mnemonics */
  109.           gv->noextmnemo = TRUE;
  110.           break;
  111.  
  112.         case 'O':  /* set output format (0=abs, 1=elf, 2=ehf, ... ) */
  113.           if (buf = get_option_arg(argc,argv,&i)) {
  114.             if ((j = atoi(buf)) > OFMT_LAST)
  115.               error(49,j);  /* unknown output format */
  116.             else
  117.               gv->output = j;
  118.           }
  119.           else
  120.             error(48,'O');  /* option -O: argument expected */
  121.           break;
  122.  
  123.         case 'I':  /* add include path */
  124.           for (j=0; j<MAX_INCPATHS; j++) {
  125.             if (gv->incpaths[j] == NULL) {
  126.               if (!(gv->incpaths[j] = get_option_arg(argc,argv,&i)))
  127.                 error(48,'I');  /* option -I: argument expected */
  128.               break;
  129.             }
  130.           }
  131.           if (j >= MAX_INCPATHS)  /* path was ignored */
  132.             error(51,MAX_INCPATHS,get_option_arg(argc,argv,&i));
  133.           break;
  134.  
  135.         case 'B':  /* base address for absolute code */
  136.           if (buf = get_option_arg(argc,argv,&i)) {
  137.             if (!(sscanf(buf,"%li",(long *)&gv->absbase)))
  138.               error(54,'B');  /* option -B: integer expected */
  139.           }
  140.           else
  141.             error(48,'B');  /* option -B: argument expected */
  142.           break;
  143.  
  144.         case 'D':  /* define a symbol */
  145.           if (buf = get_option_arg(argc,argv,&i)) {
  146.             buf = getsymbol(gv,buf);
  147.             if (*gv->strbuf) {
  148.               buf = skipspaces(buf);
  149.               if (*buf == '=')
  150.                 buf = skipspaces(++buf);
  151.               else
  152.                 buf = stdassgn;
  153.               udn = alloc(sizeof(struct UserDefine));
  154.               udn->line = alloc(8 + strlen(gv->strbuf) + strlen(buf));
  155.               sprintf(udn->line,".set %s,%s\n",gv->strbuf,buf);
  156.               addtail(&gv->userdeflist,&udn->n);
  157.             }
  158.             else
  159.               error(56,'D');  /* option -D: symbol name expected */
  160.           }
  161.           else
  162.             error(48,'D');  /* option -D: argument expected */
  163.           break;
  164.  
  165.         case 'm':  /* -m set assembler mode */
  166.           if (buf = get_option_arg(argc,argv,&i)) {
  167.             if (!strcmp(buf,"64")) {
  168.               gv->sixtyfourmode = TRUE;
  169.               break;
  170.             }
  171.             else if (*buf == 'o') {
  172.               gv->optinstrmode = TRUE;
  173.               break;
  174.             }
  175.             else if (*buf == 's') {
  176.               gv->supermode = TRUE;
  177.               break;
  178.             }
  179.           }
  180.           error(57,buf);  /* Unknown assembler mode -mX */
  181.           break;
  182.  
  183.         default:
  184.           printf("Unknown option -%c ignored.\n",argv[i][1]);
  185.           break;
  186.       }
  187.     }
  188.     else {
  189.       /* source file name */
  190.       if (gv->source_name)
  191.         error(4);  /* multiple source file names detected */
  192.       gv->source_name = argv[i];
  193.     }
  194.   }
  195.   if (!gv->source_name)
  196.     error(2);  /* missing source file name */
  197.  
  198.   if (!gv->dest_name)
  199.     gv->dest_name = default_destname(gv);    
  200.  
  201.   /* initialization */
  202.   init_hashtables(gv);
  203.  
  204.   /* assemble */
  205.   exec_pass1(gv);
  206.   exec_pass2(gv);
  207.  
  208.   /* write output file */
  209.   write_object(gv);
  210.   cleanup(gv);
  211. }
  212.  
  213.  
  214. static char *default_destname(struct GlobalVars *gv)
  215. /* make default output file name from source file name */
  216. {
  217.   char dname[STRBUFSIZE];
  218.   int i;
  219.  
  220.   strncpy(dname,gv->source_name,STRBUFSIZE-1);
  221.   i = strlen(dname);
  222.   while (i--) {
  223.     if (dname[i] == '.') {  /* replace old extension by ".o" */
  224.       dname[i] = 0;
  225.       break;
  226.     }
  227.   }
  228.   strcat(dname,".o");
  229.   return (allocstring(dname));
  230. }
  231.  
  232.  
  233. static char *get_option_arg(int argc,char *argv[],int *i)
  234. /* get pointer to the string, which either directly follows the option
  235.    character or is stored in the next argument */
  236. {
  237.   if (!argv[*i][2])
  238.     if (++*i<argc)
  239.       return (argv[*i]);
  240.     else
  241.       return NULL;
  242.   else
  243.     return (&argv[*i][2]);
  244. }
  245.  
  246.  
  247. static void write_object(struct GlobalVars *gv)
  248. /* creates the object file */
  249. {
  250.   switch(gv->output) {
  251.     case OFMT_ABSOLUTE:
  252.       output_absolute(gv);
  253.       break;
  254.     case OFMT_ELF:
  255.       output_elf32msb(gv);
  256.       break;
  257.     case OFMT_EHF:
  258.       output_ehf(gv);
  259.       break;
  260.   }
  261. }
  262.  
  263.  
  264. void cleanup(struct GlobalVars *gv)
  265. {
  266.   exit(gv->returncode);
  267. }
  268.